import * as THREE from 'three';
import Stats from 'three/examples/jsm/libs/stats.module.js';
import {GUI} from 'three/examples/jsm/libs/dat.gui.module.js';

import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import {OBJLoader} from 'three/examples/jsm/loaders/OBJLoader.js';
import {EffectComposer} from 'three/examples/jsm/postprocessing/EffectComposer.js';
import {RenderPass} from 'three/examples/jsm/postprocessing/RenderPass.js';
// import {ShaderPass} from 'three/examples/jsm/postprocessing/ShaderPass.js';// 自定义了后期
import {OutlinePass} from 'three/examples/jsm/postprocessing/OutlinePass.js';
// import {FXAAShader} from 'three/examples/jsm/shaders/FXAAShader.js'; // 抗锯齿插件

import '../../css/base.css'

let container, stats;
let camera, scene, renderer, controls;
let raycaster = new THREE.Raycaster();

let mouse = new THREE.Vector2();
let selectedObjects = [];

let composer, effectFXAA, outlinePass;
let obj3d = new THREE.Object3D();

let group = new THREE.Group();

let params = {
    edgeStrength: 3.0,
    edgeGlow: 0.0,
    edgeThickness: 1.0,
    pulsePeriod: 0,
    rotate: false,
    usePatternTexture: false
}; // 参数

function initBase() {
    container = document.createElement('div');
    document.body.appendChild(container);

    let width = window.innerWidth;
    let height = window.innerHeight;

    renderer = new THREE.WebGLRenderer();
    renderer.shadowMap.enabled = true;
    renderer.setSize(width, height);
    document.body.appendChild(renderer.domElement);

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100);
    camera.position.set(0, 0, 8);
} // 初始化三大基础
function initControls() {
    controls = new OrbitControls(camera, renderer.domElement);
    controls.minDistance = 5;
    controls.maxDistance = 20;
    controls.enablePan = false;
    controls.enableDamping = true;
    controls.dampingFactor = 0.05;
} // 初始化控制器
function initLight() {
    scene.add(new THREE.AmbientLight(0xaaaaaa, 0.2));

    let light = new THREE.DirectionalLight(0xddffdd, 0.6);
    light.position.set(1, 1, 1);

    light.castShadow = true;

    light.shadow.mapSize.width = 1024;
    light.shadow.mapSize.height = 1024;

    let d = 10;

    light.shadow.camera.left = -d;
    light.shadow.camera.right = d;
    light.shadow.camera.top = d;
    light.shadow.camera.bottom = -d;

    light.shadow.camera.far = 1000;

    scene.add(light);
}// 初始化灯光
function initModel() {
    let manager = new THREE.LoadingManager();
    manager.onProgress = function (item, loaded, total) {
        console.log(item, loaded, total);
    };
    // let loader = new OBJLoader(manager);
    // loader.load('three/examples/models/obj/tree.obj', function (object) {
    //     let scale = 1.0;
    //     object.traverse(function (child) {
    //
    //         if (child instanceof THREE.Mesh) {
    //
    //             child.geometry.center();
    //             child.geometry.computeBoundingSphere();
    //             scale = 0.2 * child.geometry.boundingSphere.radius;
    //
    //             let phongMaterial = new THREE.MeshPhongMaterial({
    //                 color: 0xffffff,
    //                 specular: 0x111111,
    //                 shininess: 5
    //             });
    //             child.material = phongMaterial;
    //             child.receiveShadow = true;
    //             child.castShadow = true;
    //
    //         }
    //
    //     });
    //
    //     object.position.y = 1;
    //     object.scale.divideScalar(scale);
    //     obj3d.add(object);
    // });
    // 生成球
    let geometry = new THREE.SphereBufferGeometry(3, 48, 24);
    for (let i = 0; i < 20; i++) {
        let material = new THREE.MeshLambertMaterial();
        material.color.setHSL(Math.random(), 1.0, 0.3);

        let mesh = new THREE.Mesh(geometry, material);
        mesh.position.x = Math.random() * 4 - 2;
        mesh.position.y = Math.random() * 4 - 2;
        mesh.position.z = Math.random() * 4 - 2;
        mesh.receiveShadow = true;
        mesh.castShadow = true;
        mesh.scale.multiplyScalar(Math.random() * 0.3 + 0.1);
        group.add(mesh);
    }

    let floorMaterial = new THREE.MeshLambertMaterial({side: THREE.DoubleSide});

    let floorGeometry = new THREE.PlaneBufferGeometry(12, 12);
    let floorMesh = new THREE.Mesh(floorGeometry, floorMaterial);
    floorMesh.rotation.x -= Math.PI * 0.5;
    floorMesh.position.y -= 1.5;
    group.add(floorMesh);
    floorMesh.receiveShadow = true;

    let geometry2 = new THREE.TorusBufferGeometry(1, 0.3, 16, 100);
    let material = new THREE.MeshPhongMaterial({color: 0xffaaff});
    let torus = new THREE.Mesh(geometry2, material);
    torus.position.z = -4;
    group.add(torus);
    torus.receiveShadow = true;
    torus.castShadow = true;

    scene.add(group);
    group.add(obj3d);
    console.log('scene: ', scene);
    {
        let geometry3 = new THREE.BoxBufferGeometry(1, 1, 1);
        let material3 = new THREE.MeshBasicMaterial({color: 0x00ff00});
        let cube = new THREE.Mesh(geometry3, material3);
        cube.name = 'cube'
        scene.add(cube);
    }
} // 初始化模型
function initHelper() {
    stats = new Stats();
    container.appendChild(stats.dom);

    function gui() {
        let gui = new GUI({width: 300});
        gui.add(params, 'edgeStrength', 0.01, 10).onChange(function (value) {
            outlinePass.edgeStrength = Number(value);
        });
        gui.add(params, 'edgeGlow', 0.0, 1).onChange(function (value) {
            outlinePass.edgeGlow = Number(value);
        });
        gui.add(params, 'edgeThickness', 1, 4).onChange(function (value) {
            outlinePass.edgeThickness = Number(value);
        });
        gui.add(params, 'pulsePeriod', 0.0, 5).onChange(function (value) {
            outlinePass.pulsePeriod = Number(value);
        });
        gui.add(params, 'rotate');
        gui.add(params, 'usePatternTexture').onChange(function (value) {
            outlinePass.usePatternTexture = value;
        });
        let Configuration = function () {
            this.visibleEdgeColor = '#ffffff';
            this.hiddenEdgeColor = '#190a05';
        };
        let conf = new Configuration();
        gui.addColor(conf, 'visibleEdgeColor').onChange(function (value) {
            outlinePass.visibleEdgeColor.set(value);
        });
        gui.addColor(conf, 'hiddenEdgeColor').onChange(function (value) {
            outlinePass.hiddenEdgeColor.set(value);
        });
    } // gui
    gui();
} // 初始化帮手
function initPostprocessing() {
    composer = new EffectComposer(renderer);

    let renderPass = new RenderPass(scene, camera);
    composer.addPass(renderPass);

    outlinePass = new OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
    composer.addPass(outlinePass);

    let onLoad = function (texture) {
        outlinePass.patternTexture = texture;
        texture.wrapS = THREE.RepeatWrapping;
        texture.wrapT = THREE.RepeatWrapping;
    };

    let loader = new THREE.TextureLoader();

    // loader.load('three/examples/textures/tri_pattern.jpg', onLoad);

    // effectFXAA = new ShaderPass(FXAAShader); // 自定义了后期
    // effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);
    // composer.addPass(effectFXAA);

    window.addEventListener('mousemove', onTouchMove);
    window.addEventListener('touchmove', onTouchMove);

    function onTouchMove(event) {
        let x, y;
        if (event.changedTouches) {
            x = event.changedTouches[0].pageX;
            y = event.changedTouches[0].pageY;
        } else {
            x = event.clientX;
            y = event.clientY;
        }
        mouse.x = (x / window.innerWidth) * 2 - 1;
        mouse.y = -(y / window.innerHeight) * 2 + 1;
        checkIntersection();
    }

    function addSelectedObject(object) {
        selectedObjects = [];
        selectedObjects.push(object);
    }

    function checkIntersection() {
        raycaster.setFromCamera(mouse, camera);
        let intersects = raycaster.intersectObjects([scene], true);
        if (intersects.length > 0) {
            let selectedObject = intersects[0].object;
            addSelectedObject(selectedObject);
            outlinePass.selectedObjects = selectedObjects;
        } else {
            outlinePass.selectedObjects = [];
        }
    }
} //postprocessing 初始化后期处理
function onWindowResize() {
    let width = window.innerWidth;
    let height = window.innerHeight;
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
    renderer.setSize(width, height);
    composer.setSize(width, height);
    // effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);
} // 控制窗口大小
function render() {
    let timer = performance.now();
    if (params.rotate) {
        group.rotation.y = timer * 0.0001;
    }
    controls.update();
    composer.render();
} // 加载器

function animate() {
    requestAnimationFrame(animate);
    render()
    stats.update();
}// 动画
(function () {
    initBase();
    initControls();
    initPostprocessing();
    initLight();
    initModel();
    initHelper()
    window.addEventListener('resize', onWindowResize, false);
    animate();
})()// 启动
